// SERVER TCP PROGRAM
// revised and tidied up by
// J.W. Atwood
// 1999 June 30
// There is still some leftover trash in this code.

/*
 * Modified for COMP 445 A1
 * Student: Jacqueline Fu and Kevin Labrie
 * Last modify date: Sep. 22th 2012 at 5:19pm
 * Professors: Dr. Ebrahim Soujeri & Dr. Aiman Hanna
 */

/* send and receive codes between client and server */
/* This is your basic WINSOCK shell */
#pragma once
#pragma comment( linker, "/defaultlib:ws2_32.lib" )
#include <winsock2.h>
#include <ws2tcpip.h>
#include <process.h>
#include <winsock.h>
#include <stdio.h>
#include <iostream>
#include <windows.h>
//==================
#include <fstream>
#include <string>
#include <ctime>
#include "..\router\Router.h"
//==================

using namespace std;

//port data types

#define REQUEST_PORT 5001

int port=REQUEST_PORT;

#define TRACE 1

//socket data types
SOCKET s;
SOCKADDR_IN sa;			// server info, IP, port 5001		// filled by bind
SOCKADDR_IN sa_in;		// router info, IP, port 7001		//fill with server info, IP, port
union {struct sockaddr generic;
	struct sockaddr_in ca_in;}ca;

int calen=sizeof(ca); 

int const MAX_SIZE = 128;
int const MAX = 260;
//buffer data types
char szbuffer[128];
char *buffer;
int ibufferlen;
int ibytesrecv;
int ibytessent;

//host data types
char localhost[11];
	HOSTENT *hp;

//wait variables
int nsa1;
int r,infds=1, outfds=0;
struct timeval timeout;
struct timeval *tp=&timeout;
	fd_set readfds;
//variables for the timer
#define UTIMER 300000
#define STIMER 0 
struct timeval timeouts;

//others
HANDLE test;
DWORD dwtest;

//other variables
int bitsread;
int bitsleft;

//reference for used structures

/*  * Host structure

struct  hostent 
{
    char    FAR * h_name;             official name of host *
    char    FAR * FAR * h_aliases;    alias list *
    short   h_addrtype;               host address type *
    short   h_length;                 length of address *
    char    FAR * FAR * h_addr_list;  list of addresses *
	#define h_addr  h_addr_list[0]    address, for backward compat *
};

 * Socket address structure

struct sockaddr_in 
{
	short   sin_family;
	u_short sin_port;
	struct  in_addr sin_addr;
	char    sin_zero[8];
}; sa_in*/

// ADDED FOR 3-WAY-HANDSHAKE
//#define STOPNWAIT 1 //Bits width For stop and wait
struct MESSAGE_FRAME 
{
	unsigned char header;		//ERROR,DATA,LASTPACKET, etc.
	unsigned int snwseq;//:STOPNWAIT;
	char data[MAX_SIZE]; 		//data or error message
} message_frame;

struct THREE_WAY_HS
{
	int client_number;
	int server_number;
	char direction;
	char file_name[MAX];
} three_way_hs;

struct DATA_FRAME 
{
	unsigned char header;		//ERROR,DATA,LASTPACKET, etc.
	char data[MAX]; 		//data or error message
} data_frame;

int servernum;
int clientnum;
int clientseqnum;
int serverseqnum;

int main(void)
{	
	// Handshake
	THREE_WAY_HS three_way_hs;
	srand((unsigned)time(NULL));
	
	timeouts.tv_sec=STIMER;
	timeouts.tv_usec=UTIMER;
	
	//create log file and open for writting
	FILE* filelog;
	filelog = fopen("serverlog.txt", "w");

	WSADATA wsadata;

	try
	{        		 
		if (WSAStartup(0x0202,&wsadata)!=0)
		{  
			cout<<"Error in starting WSAStartup()\n";
		}
		else
		{
			buffer="WSAStartup was suuccessful\n";   
			WriteFile(test,buffer,sizeof(buffer),&dwtest,NULL); 

			/* display the wsadata structure */
			cout<< endl
				<< "wsadata.wVersion "       << wsadata.wVersion       << endl
				<< "wsadata.wHighVersion "   << wsadata.wHighVersion   << endl
				<< "wsadata.szDescription "  << wsadata.szDescription  << endl
				<< "wsadata.szSystemStatus " << wsadata.szSystemStatus << endl
				<< "wsadata.iMaxSockets "    << wsadata.iMaxSockets    << endl
				<< "wsadata.iMaxUdpDg "      << wsadata.iMaxUdpDg      << endl;
		}  

		//Display info of local host
		gethostname(localhost,10);
		cout << "hostname: " <<localhost << endl;

		if((hp=gethostbyname(localhost)) == NULL) 
		{
			cout << "gethostbyname() cannot get local host info?"
				<< WSAGetLastError() << endl; 
			exit(1);
		}

		//Create the server socket
		if((s = socket(AF_INET,SOCK_DGRAM,0)) == INVALID_SOCKET) 
			throw "can't initialize socket";
		// For UDP protocol replace SOCK_STREAM with SOCK_DGRAM 

		//Fill-in Server Port and Address info.
		//memset(&sa,0,sizeof(sa));
		sa.sin_family = AF_INET;
		sa.sin_port = htons(PEER_PORT2);
		sa.sin_addr.s_addr = htonl(INADDR_ANY);		//Host to network

		//Bind the server port
		if (bind(s,(LPSOCKADDR)&sa,sizeof(sa)) == SOCKET_ERROR)
			throw "can't bind the socket";
		cout << "Bind was successful" << endl;

		FD_ZERO(&readfds);

		FD_SET(s,&readfds);

		//variable to hold clenthostname
		char clientHostName[128] = {0};

		//length of sockaddr struct
		int len = sizeof(struct sockaddr);

		while(true)
		{
			//notify client action
			cout << "Client is making a request..." << endl;

			//start of three way handshake
			//timeout loop to recieve client number in three way handshake
			while(true)
			{
				
				FD_ZERO(&readfds);

				FD_SET(s,&readfds);  //always check the listener

				//timeout is 0 therefore waits forever until it recieves something
				outfds = select (1 , &readfds, NULL, NULL, 0);

				if (outfds) //if outfds is 1, data has been recieved
					break;

				//if outfds is 0, no data received yet so does nothing and keeps waiting
			}

			//recieve client number in three way handshake
			//form of recvfrom(socket, buffer, buffer length, flags, socket address, sockey address length);
			if (outfds == 1) //receive frame
				ibytesrecv = recvfrom(s, (char*)&three_way_hs, sizeof(three_way_hs), 0, (struct sockaddr*)&sa, &len);

			//check for error else display direction of tranfer delete is char d, get (send) is char g and put (store) is char p
			if(ibytesrecv == SOCKET_ERROR)
				throw "Receive error in server program\n";

			//create server number for three way handshake
			servernum = rand() % 256;
			three_way_hs.server_number = servernum;
				
			//quit program if direction q is recieved
			if(three_way_hs.direction == 'q')
				break;
			else if(three_way_hs.direction == 'l')
				cout << "List all files on server." << endl;
			else if(three_way_hs.direction == 'd')
				cout << three_way_hs.file_name << " to be deleted." << endl;
			else if(three_way_hs.direction == 'g')
					cout << three_way_hs.file_name << " to be sent." << endl;
			else if(three_way_hs.direction == 'g')
					cout << three_way_hs.file_name << " to be stored." << endl;

			//time out loop to recieve client ack in three way handshake
			while(true)
			{
				FD_ZERO(&readfds);

				FD_SET(s,&readfds);

				//send server number in three way handshake
				//form of sendto(socket, datagram, datagram length, flags, addr, addr length);
				sendto(s, (char*)&three_way_hs, sizeof(three_way_hs), 0, (struct sockaddr*)&sa, sizeof(sa));

				//timeout is 300ms
				outfds = select (1 , &readfds, NULL, NULL, &timeouts);

				if (outfds) //if outfds is 1, data has been recieved
					break;

				//if outfds is 0, no data received yet so does nothing and keeps waiting
			}

			//recieve client ack to finish three way handshake
			ibytesrecv = recvfrom(s, (char*)&three_way_hs, sizeof(three_way_hs), 0, (struct sockaddr*)&sa, &len);

			//check for error
			if(ibytesrecv == SOCKET_ERROR)
				throw "Receive error in server program\n";
			if(three_way_hs.server_number != servernum) //check if recieved server number is the same as first created
				throw "Receive error in server number\n";

			//threee way handshake complete!

			//determine initial sequence numbers (0 if number is even, 1 if it is odd)
			serverseqnum = three_way_hs.client_number % 2;
			clientseqnum = three_way_hs.server_number % 2;

			//direction is list i.e. char l, list all files on server
			if(three_way_hs.direction == 'l')
			{
				//directory search variables
				WIN32_FIND_DATA fd;
				HANDLE h = FindFirstFile("*.*", &fd);
 
				while(1)
				{
					//if no files on server send error message
					if(h == INVALID_HANDLE_VALUE)
					{
						//time out loop to recieve client ack
						while(true)
						{
							FD_ZERO(&readfds);

							FD_SET(s,&readfds);

							message_frame.header = 'e'; //error no files on server
							message_frame.snwseq = serverseqnum; //send seq num

							//send error packet
							//send(s, (char *)&data_frame, sizeof(data_frame), 0);	//For TCP
							sendto(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, sizeof(sa));

							//print info to log
							if(TRACE)
							{
								fprintf(filelog, "Sender: sent packet %d\n", message_frame.snwseq);
							}

							//timeout is 300ms
							outfds = select (1 , &readfds, NULL, NULL, &timeouts);

							if (outfds) //if outfds is 1, data has been recieved
								break;
							{
								//recieve client ack to finish three way handshake
								ibytesrecv = recvfrom(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, &len);

								//print info to log
								if(TRACE)
								{
									fprintf(filelog, "Sender: received ACK for packet %d\n", message_frame.snwseq);
								}

								//check for error
								if(ibytesrecv == SOCKET_ERROR)
									throw "Receive error in server program\n";

								//check if seqnum are the same
								if(serverseqnum == message_frame.snwseq) //if yes packet was received by client
								{
									//add 1 to seqnum
									serverseqnum = serverseqnum + 1;
									break;
								}

								//else resend packet
							}

							//if outfds is 0, no data received yet, restart loop and resend message
						}

						break; // no files found
					}

					while(true)
					{
						FD_ZERO(&readfds);

						FD_SET(s,&readfds);

						//seqnum
						message_frame.snwseq = serverseqnum;

						//if there are files on the server
						message_frame.header = 'f'; //char f indicates first or middle file on server

						//clear data_frame.data
						memset(message_frame.data, 0, sizeof(message_frame.data));

						//place file name into packet
						strcpy_s(message_frame.data,sizeof(message_frame.data),fd.cFileName);

						//send file name to client
						//send(s, (char *)&data_frame, sizeof(data_frame), 0);	//For TCP
						sendto(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, sizeof(sa));

						//print info to log
						if(TRACE)
						{
							fprintf(filelog, "Sender: sent packet %d\n", message_frame.snwseq);
						}

						//timeout is 300ms
						outfds = select (1 , &readfds, NULL, NULL, &timeouts);

						if (outfds) //if outfds is 1, data has been recieved
						{
							//recieve client ack to finish three way handshake
							ibytesrecv = recvfrom(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, &len);

							//print info to log
							if(TRACE)
							{
								fprintf(filelog, "Sender: received ACK for packet %d\n", message_frame.snwseq);
							}

							//check for error
							if(ibytesrecv == SOCKET_ERROR)
								throw "Receive error in server program\n";

							//check if seqnum are the same
							if(serverseqnum == message_frame.snwseq) //if yes packet was received by client
							{
								//add 1 to seqnum
								serverseqnum = serverseqnum + 1;
								break;
							}
							

							//else resend packet
						}

						//if outfds is 0, no data received yet, restart loop and resend message
					}

 
					//if no more files on server left to display
					if(FindNextFile(h, &fd) == FALSE)
					{
						while(true)
						{
							FD_ZERO(&readfds);

							FD_SET(s,&readfds);

							//seqnum
							message_frame.snwseq = serverseqnum;

							message_frame.header = 'l'; //char l indicates no more files left on server

							//clear data_frame.data
							memset(message_frame.data, 0, sizeof(message_frame.data));

							//send packet indicating no more files left on the server
							//send(s, (char *)&data_frame, sizeof(data_frame), 0); //For TCP
							sendto(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, sizeof(sa));

							//print info to log
							if(TRACE)
							{
								fprintf(filelog, "Sender: sent packet %d\n", message_frame.snwseq);
							}

							//timeout is 300ms
							outfds = select (1 , &readfds, NULL, NULL, &timeouts);

							if (outfds) //if outfds is 1, data has been recieved
							{
								//recieve client ack to finish three way handshake
								ibytesrecv = recvfrom(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, &len);

								//print info to log
								if(TRACE)
								{
									fprintf(filelog, "Sender: received ACK for packet %d\n", message_frame.snwseq);
								}

								//check for error
								if(ibytesrecv == SOCKET_ERROR)
									throw "Receive error in server program\n";

								//check if seqnum are the same
								if(serverseqnum == message_frame.snwseq) //if yes packet was received by client
								{
									//add 1 to seqnum
									serverseqnum = serverseqnum + 1;
									break;
								}

								//else resend packet
							}

							//if outfds is 0, no data received yet, restart loop and resend message
						}

						//print info to log
						if(TRACE)
						{
							fprintf(filelog, "Sender: transfer completed");
						}

						break;
					}
				}
			}
			else if(three_way_hs.direction == 'd') //direction is delete i.e. char d, delete requested file from server
			{
				//open file to be deleted as filedel 
				ifstream filedel;

				//open for input in binary mode (mode doesn't really matter)
				filedel.open(three_way_hs.file_name, ios_base::in | ios_base::binary );

				//check if the requested file exists
				if (!filedel.is_open()) //file does not exit
				{
					while(true)
					{
						//send packet to client indicating the file doesn't exist on the server
						message_frame.header = 'e'; //char e indicates an error

						message_frame.snwseq = serverseqnum; //send seq num
					
						//send error message to client
						//send(s, (char *)&message_frame, sizeof(message_frame), 0);	//For TCP
						sendto(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, sizeof(sa));

						//print info to log
						if(TRACE)
						{
							fprintf(filelog, "Sender: sent packet %d\n", message_frame.snwseq);
						}

						//timeout is 300ms
						outfds = select (1 , &readfds, NULL, NULL, &timeouts);

						if (outfds) //if outfds is 1, data has been recieved
						{
							//recieve client ack to finish three way handshake
							ibytesrecv = recvfrom(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, &len);

							//print info to log
							if(TRACE)
							{
								fprintf(filelog, "Sender: received ACK for packet %d\n", message_frame.snwseq);
							}

							//check for error
							if(ibytesrecv == SOCKET_ERROR)
								throw "Receive error in server program\n";

							//check if seqnum are the same
							if(serverseqnum == message_frame.snwseq) //if yes packet was received by client
							{
								//if file does not exist: error message
								cout <<"ERROR: File Does Not Exist!" << endl;
								cout << "File " << three_way_hs.file_name << " cannot be deleted!" << endl;

								//print info to log
								if(TRACE)
								{
									fprintf(filelog, "Sender: transfer completed");
								}

								//add 1 to seqnum
								serverseqnum = serverseqnum + 1;
								break;
							}

							//else resend packet
						}
					}
				}
				else //file exists on server
				{
					//close file
					filedel.close();

					//delete requested file
					remove(three_way_hs.file_name);

					while(true)
					{
						//send packet to client indicating the file deleted
						message_frame.header = 's'; //char s indicates success

						message_frame.snwseq = serverseqnum; //send seq num

						//send success message to client
						//send(s, (char *)&message_frame, sizeof(message_frame), 0);	//For TCP
						sendto(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, sizeof(sa));

						//print info to log
						if(TRACE)
						{
							fprintf(filelog, "Sender: sent packet %d\n", message_frame.snwseq);
						}

						//timeout is 300ms
						outfds = select (1 , &readfds, NULL, NULL, &timeouts);

						if (outfds) //if outfds is 1, data has been recieved
						{
							//recieve client ack
							ibytesrecv = recvfrom(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, &len);

							//print info to log
							if(TRACE)
							{
								fprintf(filelog, "Sender: received ACK for packet %d\n", message_frame.snwseq);
							}

							//check for error
							if(ibytesrecv == SOCKET_ERROR)
								throw "Receive error in server program\n";

							//check if seqnum are the same
							if(serverseqnum == message_frame.snwseq) //if yes packet was received by client
							{
								//print info to log
								if(TRACE)
								{
									fprintf(filelog, "Sender: transfer completed");
								}

								//add 1 to seqnum
								serverseqnum = serverseqnum + 1;
								break;
							}

							//else resend packet
						}
					}
				}
			}
			else //if direction is get i.e. char g, send file to client
				if(three_way_hs.direction == 'g')
				{
					//message saying file is being sent
					cout << "Sending file to " << clientHostName << ", waiting..." << endl;

					//open file to be sent as fileout 
					ifstream fileout;

					//open for input in binary mode
					fileout.open(three_way_hs.file_name, ios_base::in | ios_base::binary );

					//check if the requested file exists
					if (!fileout.is_open()) //file does not exit
					{
						while(true)
						{
							//send packet to client indicating the file doesn't exist on the server
							message_frame.header = '9'; //char 9 indicates an error

							message_frame.snwseq = serverseqnum; //send seq num
					
							//send error message to client
							//send(s, (char *)&message_frame, sizeof(message_frame), 0);	//For TCP
							sendto(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, sizeof(sa));

							//print info to log
							if(TRACE)
							{
								fprintf(filelog, "Sender: sent packet %d\n", message_frame.snwseq);
							}

							//timeout is 300ms
							outfds = select (1 , &readfds, NULL, NULL, &timeouts);

							if (outfds) //if outfds is 1, data has been recieved
							{
								//recieve client ack to finish three way handshake
								ibytesrecv = recvfrom(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, &len);

								//print info to log
								if(TRACE)
								{
									fprintf(filelog, "Sender: received ACK for packet %d\n", message_frame.snwseq);
								}

								//check for error
								if(ibytesrecv == SOCKET_ERROR)
									throw "Receive error in server program\n";

								//check if seqnum are the same
								if(serverseqnum == message_frame.snwseq) //if yes packet was received by client
								{
									//if file does not exist: error message
									cout <<"ERROR: File Does Not Exist!" << endl;
									cout << "File " << three_way_hs.file_name << " cannot be sent to client " << clientHostName << "!" << endl;

									//print info to log
									if(TRACE)
									{
										fprintf(filelog, "Sender: transfer completed");
									}

									//add 1 to seqnum
									serverseqnum = serverseqnum + 1;
									break;
								}

								//else resend packet
							}
						}
					}
					else //file exists
					{
						//get the file size
						fileout.seekg (0, ios::end);
						int filesize = fileout.tellg();
						fileout.seekg (0, ios::beg);

						//keep track of the bits already read
						bitsread = 0;

						//keep track of the bits left to read
						bitsleft = filesize;

						//bool to flag when the file as been completely received
						bool lastpacket = false;

						//keep sending packets containing the file data until there are no more bits to read
						while(lastpacket == false)
						{
							//if data is at the begining or middle of the file
							if(bitsleft > MAX_SIZE)
							{
								//read data into the packet until the alloted size is reached
								fileout.read(message_frame.data, MAX_SIZE);

								while(true)
								{
									//char b means this packet is in the middle
									message_frame.header = 'b';

									message_frame.snwseq = serverseqnum; //send seq num

									//send packet to server
									//send(s, (char *)&message_frame, sizeof(message_frame), 0);	//For TCP
									sendto(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, sizeof(sa));

									//print info to log
									if(TRACE)
									{
										fprintf(filelog, "Sender: sent packet %d\n", message_frame.snwseq);
									}

									//timeout is 300ms
									outfds = select (1 , &readfds, NULL, NULL, &timeouts);

									if (outfds) //if outfds is 1, data has been recieved
									{
										//recieve client ack to finish three way handshake
										ibytesrecv = recvfrom(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, &len);

										//print info to log
										if(TRACE)
										{
											fprintf(filelog, "Sender: received ACK for packet %d\n", message_frame.snwseq);
										}

										//check for error
										if(ibytesrecv == SOCKET_ERROR)
											throw "Receive error in server program\n";

										//check if seqnum are the same
										if(serverseqnum == message_frame.snwseq) //if yes packet was received by client
										{
											//add 1 to seqnum
											serverseqnum = serverseqnum + 1;
											break;
										}

										//else resend packet
									}
								}
								
								//change bits read and bits left accordingly
								bitsleft = bitsleft - MAX_SIZE;
								bitsread = bitsread + MAX_SIZE;

								//flag that this is not the last packet
								lastpacket = false;
							}
							else if(bitsleft <= MAX_SIZE) //if data is at the end of the file
							{
								//since we will not fill the entire message_frame.data, clear it
								memset(message_frame.data, 0, sizeof(message_frame.data));

								//read data into the packet until the alloted size is reached
								fileout.read(message_frame.data, bitsleft);

								while(true)
								{
									//packet is the last
									message_frame.header = (unsigned char)bitsleft;

									message_frame.snwseq = serverseqnum; //send seq num

									//send packet to server
									//send(s, (char *)&message_frame, sizeof(message_frame), 0);	//For TCP
									sendto(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, sizeof(sa));

									//print info to log
									if(TRACE)
									{
										fprintf(filelog, "Sender: sent packet %d\n", message_frame.snwseq);
									}

									//timeout is 300ms
									outfds = select (1 , &readfds, NULL, NULL, &timeouts);

									if (outfds) //if outfds is 1, data has been recieved
									{
										//recieve client ack to finish three way handshake
										ibytesrecv = recvfrom(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, &len);

										//print info to log
										if(TRACE)
										{
											fprintf(filelog, "Sender: received ACK for packet %d\n", message_frame.snwseq);
										}

										//check for error
										if(ibytesrecv == SOCKET_ERROR)
											throw "Receive error in server program\n";

										//check if seqnum are the same
										if(serverseqnum == message_frame.snwseq) //if yes packet was received by client
										{
											//add 1 to seqnum
											serverseqnum = serverseqnum + 1;
											break;
										}

										//else resend packet
									}
								}
								//change bits read and bits left accordingly
								bitsleft = bitsleft - bitsleft;
								bitsread = bitsread + bitsleft;

								//flag that this is the last packet
								lastpacket = true;
							}
						}
					}

					//get file size
					fileout.seekg(0, ios::end);
					int filesizeout = fileout.tellg();

					//close the file
					fileout.close();

					//print info to log
					if(TRACE)
					{
						fprintf(filelog, "Sender: transfer completed");
					}

					//print info to log
					if(TRACE)
					{
						fprintf(filelog, "Sender: number of bytes received: %d\n", filesizeout);
					}

					//send message as long as there is no error
					if(message_frame.header != '9')
					{
						//message saying file has been sent
						cout << "File " << three_way_hs.file_name << " sent to client " << clientHostName << "!" << endl;
					}
				}
				else if(three_way_hs.direction == 'p') //direction is put i.e. char p, store file sent from client
				{
					//message saying file is being received
					cout << "Receiving file from " << clientHostName << ", waiting..." << endl;

					//create file to write to as filein
					ofstream filein;

					//open for output in binary mode (overwrite file if it already exists)
					filein.open(three_way_hs.file_name, ios::out | ios::binary );

					//bool to flag when the file as been completely received
					bool lastpacket = false;

					//continue recieving packets of file until none are left i.e. receive packet indicating end of file
					while(lastpacket == false)
					{
						//timeout loop to recieve file packet
						while(true)
						{
							FD_ZERO(&readfds);

							FD_SET(s,&readfds);

							//timeout is 300ms
							outfds = select (1 , &readfds, NULL, NULL, &timeouts);

							if (outfds) //if outfds is 1, data has been recieved
								break;

							//if outfds is 0, no data received yet so does nothing and keeps waiting
						}

						//recieve file packet
						ibytesrecv = recvfrom(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, &len);

						//print info to log
						if(TRACE)
						{
							fprintf(filelog, "Receiver: receive packet %d\n", message_frame.snwseq);
						}

						//check for error else recieve packets
						if(ibytesrecv == SOCKET_ERROR)
							throw "Receive error in server program\n";

						//send ack to server
						sendto(s, (char*)&message_frame, sizeof(message_frame), 0, (struct sockaddr*)&sa, sizeof(sa));

						//print info to log
						if(TRACE)
						{
							fprintf(filelog, "Receiver: sent an ACK for packet %d\n", message_frame.snwseq);
						}

						if(message_frame.snwseq == serverseqnum)
						{
							switch (message_frame.header)
							{
								case 'b': //beginning or middle of file
									//write packet to file
									filein.write (message_frame.data, sizeof(message_frame.data));

									cout << "data: " << message_frame.data << endl;
								
									//flag that this is not the last packet
									lastpacket = false;
									break;
								default: //end of file
									//write packet to file
									filein.write (message_frame.data, (int)message_frame.header);

									cout << "data: " << message_frame.data << endl;

									//flag that this is the last packet
									lastpacket = true;
									break;
							}

							//add 1 to seqnum
							clientseqnum = clientseqnum + 1;
						}
					}

					//get file size
					filein.seekp(0, ios::end);
					int filesizein = filein.tellp();

					//close the file
					filein.close();

					//print info to log
					if(TRACE)
					{
						fprintf(filelog, "Receiver: transfer completed");
					}

					//print info to log
					if(TRACE)
					{
						fprintf(filelog, "Reciever: number of bytes received: %d\n", filesizein);
					}

					//message saying file has been received
					cout << "File " << three_way_hs.file_name << " received from client " << clientHostName << "!" << endl;
				}

		}//while loop

	} //try loop

	//Display needed error message.

	catch(char* str)
	{
		cerr<<str<<WSAGetLastError()<<endl;
	}

	//close Client socket
	closesocket(s);		

	//close server socket
	closesocket(s);

	/* When done uninstall winsock.dll (WSACleanup()) and exit */ 
	WSACleanup();

	//message that program is exiting
	cout << "System is quitting..." << endl;

	//close log file
	fclose (filelog);

	return 0;
}